// 导入必要的工具类和注释处理类
import makeLexerClass from '../utils/makeLexerClass'
import SLComment from './SLComment'
import MLComment from './MLComment'

// 定义CJK字符范围
const cjk = '\u2E80-\u2FD5\u3190-\u319f\u3400-\u4DBF\u4E00-\u9FCC\uF900-\uFAAD'
// 定义字母字符范围，包括CJK字符
const letter = `A-Za-z\u00C0-\u024F${cjk}`
// 定义音高表示规则
const pitch = '[#nb]*[1-7][,\']*'

// 使用makeLexerClass工厂函数创建Lexer类，定义一系列的词法规则
const Lexer = makeLexerClass({
  // 以下为各类符号和关键字的词法规则
  0: '0',
  ',': ',',
  '"': '"',
  'esc-dq': '\\\\"',
  '/': '\\/',
  '\\': '\\\\',
  '<': '<',
  '>': '>',
  '|': '\\|',
  '~': '~',
  '-': '-',
  '(': '\\(',
  ')': '\\)',
  '[': '\\[',
  ']': '\\]',
  ':': ':',
  '/\\': '[\\/\\\\]',  // 方向 / 或 \

  '==': '==',  // part-head
  '--': '--',  // staff-head
  '//': '\\/\\/',
  '/*': '\\/\\*',
  '*/': '\\*\\/',
  '<<': '<<',
  '>>': '>>',

  digit: '\\d',
  digits: '\\d+',
  paran: '[\\(\\)]',
  letter: `[${letter}]`,
  word: `[${letter}]+`,
  words: `[${letter} ]+`,

  title: 'title:',
  subtitle: 'subtitle:',
  composer: 'composer:',
  lyricist: 'lyricist:',
  arranger: 'arranger:',
  source: 'source:',
  tempo: 'tempo:',
  // abbreviation: `[${letter}\\.]+`,
  midi: 'midi', channel: 'channel', program: 'program', pan: 'pan',

  beats: '[1-9]\\d{0,3}',
  beatType: '[1-9]\\d{0,3}',
  step: '[1-7]',
  accidental: '(#{1,2}|n|b{1,2})',
  octave: `('{1,5}|,{1,5})`,
  type: '(---|-|={0,5}_|={1,5})',
  dots: '\\.{1,2}',
  pitch,
  duration: '[-_=]*\.{1,2}',

  // Filters
  time: '[1-9]\\d{0,3}\\/',
  note: `\\(*(\\[\\d+:)*${pitch}`,
  rest: '0',
  chord: `\\(*(\\[\\d+:)*<`, // `\\(*(\\[\\d+:)*<(${pitch})*>`,
  multipart: '<<',
  direction: `[\\/\\\\]+`,
  bar: '(:\\|:?|\\|:|\\|[\\|\\]]?)',

  wedge: 'wedge',
  dynamics: '(p{1,6}|f{1,6}|m[pf]|sfp{0,2}|fp|rfz?|sf{1,2}z|fz)',
  'tuplet-begin': '\\[\\d+:',
  'tuplet-end': ':\\]',

  'lyrics-head': 'lyrics.*:',
  lyric: `([\u0021-\u002C\u002E-\u007E\u00C0-\u024F\u1E00-\u1EFF]+|[${cjk}])`,
  'lyric-control': '[@\\+\\-]m?\\d',
  'lyric-control-symbol': '[@\\+\\-]',
  'm': 'm',

  cell: '([\\(\\[]*[#nb]?\\d|<|[\\:\\|]|[\\/\\\\])',
  'part-head': '==',
  'staff-head': '--',

  'sl-comment': '\\/\\/',
  'ml-comment': '\\/\\*',
  comment: '\\/[\\/\\*]',
  'comment-or-paren': '(\\/[\\/\\*]|[\\(\\)])',
  'comment-or-space': '(\\/[\\/\\*]| )',

  'all': '.*'
})

// Lexer类的skipWhite方法，用于跳过空白字符和注释
Lexer.prototype.skipWhite = function () {
  // 当前位置为换行、注释或EOF时执行跳过逻辑
  while ((this.is('S') || this.is('comment') || this.eol) && !this.eof) {
    if (this.eol) {
      this.nextLine()  // 遇到换行时，调用换行处理方法
    } else if (this.is('S')) {
      this.token('SS')  // 遇到空白字符时，生成相应的token
    } else if (this.is('sl-comment')) {
      new SLComment(this)  // 遇到单行注释时，创建并处理单行注释
    } else {
      new MLComment(this)  // 遇到多行注释时，创建并处理多行注释
    }
  }
}

// 导出Lexer类，供其他模块使用
export default Lexer
